﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data.EntityClient;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Windows.Input;
using Analyzer;
using Analyzer.ViewModel;
using Model;

namespace ReportBrowser.ViewModel
{
    internal class MainWindowViewModel : ViewModelBase, IDataErrorInfo
    {
        #region Lifecycle

        public MainWindowViewModel()
        {
            this.FilterType = ViewModel.FilterType.QualityProfileFilter;
            this.MessagesVM = new MessagesViewModel(this);
            this.Places = new PlacesViewModel(this.MessagesVM);

            #region Desig-time data
            if (DesignerProperties.GetIsInDesignMode(new System.Windows.DependencyObject()) == true)
            {
                for (int i = 0; i < 5; i++)
                {
                    QualityProfileItem qpi =
                        new QualityProfileItem()
                        {
                            CategoryName = "QPI" + i.ToString(),
                            Weight = i
                        };
                    this.QualityProfileItems.Add(qpi);
                    this.FilterOptions.Add(qpi);
                }
            }
            #endregion Desig-time data

            this.PropertyChanged += new PropertyChangedEventHandler(MainWindowViewModel_PropertyChanged);
        }

        #endregion Lifecycle

        #region Properties

        private ActualEntities pContext;
        public ActualEntities Context
        {
            get { return pContext; }
            private set
            {
                if (value != pContext)
                {
                    pContext = value;
                    OnPropertyChanged("Context");
                }
            }
        }

        #region Presentation

        private FilterType pFilterType;
        public FilterType FilterType
        {
            get { return pFilterType; }
            set
            {
                if (value != pFilterType)
                {
                    pFilterType = value;
                    OnPropertyChanged("FilterType");
                }
            }
        }

        private ObservableCollection<QualityProfileItem> pQualityProfileItems;
        public ObservableCollection<QualityProfileItem> QualityProfileItems
        {
            get
            {
                if (pQualityProfileItems == null)
                    pQualityProfileItems = new ObservableCollection<QualityProfileItem>();
                return pQualityProfileItems;
            }
        }

        private bool pIsProportional;
        public bool IsProportional
        {
            get { return pIsProportional; }
            set
            {
                if (value != pIsProportional)
                {
                    pIsProportional = value;
                    OnPropertyChanged("IsProportional");
                }
            }
        }

        private ObservableCollection<QualityProfileItem> pFilterOptions;
        public ObservableCollection<QualityProfileItem> FilterOptions
        {
            get
            {
                if (pFilterOptions == null)
                    pFilterOptions = new ObservableCollection<QualityProfileItem>();
                return pFilterOptions;
            }
        }

        public MessagesViewModel MessagesVM { get; private set; }

        public PlacesViewModel Places { get; private set; }

        #endregion Presentation

        #endregion Properties

        #region Commands

        #region BrowseReportCommand

        private RelayCommand pBrowseReportCommand;
        public ICommand BrowseReportCommand
        {
            get
            {
                if (pBrowseReportCommand == null)
                    pBrowseReportCommand =
                        new RelayCommand(
                            param =>
                            {
                                Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog();
                                ofd.AddExtension = true;
                                ofd.DefaultExt = ".db3";
                                ofd.Filter = "Adatbázis|*.db3";
                                ofd.FilterIndex = 0;
                                ofd.Title = "Riport tallózása";
                                ofd.ValidateNames = true;
                                ofd.Multiselect = false;
                                ofd.CheckFileExists = true;
                                ofd.CheckPathExists = true;
                                bool? success = ofd.ShowDialog();
                                if (success.HasValue && success.Value == true)
                                {
                                    new BrowseReportCommandAide(LoadDB).BeginInvoke(
                                        ofd.FileName,
                                        new AsyncCallback(BrowseReportCommandAide_CallbackMethod),
                                        null);
                                }
                            }
                        );
                return pBrowseReportCommand;
            }
        }

        delegate void BrowseReportCommandAide(string fileName);

        private void LoadDB(string fileName)
        {
            EntityConnectionStringBuilder builder = new EntityConnectionStringBuilder();
            builder.Metadata = "res://*/ActualModel.csdl|res://*/ActualModel.ssdl|res://*/ActualModel.msl";
            builder.Provider = "System.Data.SQLite";
            builder.ProviderConnectionString = "data source=\"" + fileName + "\"";
            if (this.Context != null)
                this.Context.Dispose();
            this.Context = new ActualEntities(builder.ConnectionString);
            this.MessagesVM.Context = new ActualEntities(builder.ConnectionString);
            this.Places.Context = new ActualEntities(builder.ConnectionString);
            RefreshQualityProfileItems();
            RefreshFilterOptions();
            RefreshOutput();
        }

        private void BrowseReportCommandAide_CallbackMethod(IAsyncResult result)
        {
            BrowseReportCommandAide caller =
                (BrowseReportCommandAide)((AsyncResult)result).AsyncDelegate;
            caller.EndInvoke(result);
        }

        #endregion BrowseReportCommand

        private RelayCommand pRefreshByFilterOptions;
        public ICommand RefreshByFilterOptions
        {
            get
            {
                if (pRefreshByFilterOptions == null)
                {
                    pRefreshByFilterOptions = new RelayCommand(
                        param => RefreshOutput(),
                        param => this.Context != null && this.Context.QualityCharacteristics.Count() > 0);
                }
                return pRefreshByFilterOptions;
            }
        }

        #endregion Commands

        #region Methods

        private void RefreshQualityProfileItems()
        {
            DispatchService.Dispatch(() =>
                {
                    this.QualityProfileItems.Clear();
                    //this.QualityProfileItems =
                    //    new ObservableCollection<QualityProfileItem>(this.Context.QualityProfileItems);
                    foreach (var qpi in this.Context.QualityProfileItems)
                        this.QualityProfileItems.Add(qpi);
                });
        }

        private void RefreshFilterOptions()
        {
            DispatchService.Dispatch(() =>
                {
                    this.FilterOptions.Clear();
                    foreach (var item in this.Context.Categories)
                        this.FilterOptions.Add(new QualityProfileItem() { CategoryName = item.Name, Weight = 0 });
                });
        }

        private void RefreshOutput()
        {
            this.MessagesVM.Refresh(this.FilterType, this.IsProportional);
            this.Places.Refresh();
        }

        #endregion Methods

        #region EventHandlers

        void MainWindowViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "NumberOfMessagesToShow":
                case "IsProportional":
                    RefreshOutput();
                    break;
                case "FilterType":
                    switch (this.FilterType)
                    {
                        //case FilterType.None:
                        //    break;
                        case FilterType.QualityProfileFilter:
                        case FilterType.CustomFilter:
                            this.MessagesVM.IsNumberOfMessagesToShowEnabled = true;
                            break;
                        case FilterType.ShowAll:
                            this.MessagesVM.IsNumberOfMessagesToShowEnabled = false;
                            break;
                        default:
                            break;
                    }
                    RefreshOutput();
                    break;
                default:
                    break;
            }
        }

        #endregion EventHandlers

        #region IDataErrorInfo Members

        public string Error
        {
            get { throw new NotImplementedException(); }
        }

        public string this[string columnName]
        {
            get
            {
                string msg = null;
                switch (columnName)
                {
                    default:
                        throw new ArgumentException(
                            "Unrecognised property " + columnName + " !", "columnName");
                }
                return msg;
            }
        }

        #endregion IDataErrorInfo Members
    }
}
